from zope.interface import implements
from repoze.who.interfaces import IAuthenticator
from repoze.who.interfaces import IIdentifier
from repoze.who.interfaces import IMetadataProvider

from apkn.portal.users import User, Base
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

Session = sessionmaker()

#will be moved to who.ini configuration
SCHEMA_SEARCH_PATH = "pas,public"

class SqlalchemyWhoPlugin(object):

	implements (IIdentifier, IAuthenticator, IMetadataProvider)
	
	def __init__(self, db_uri):
		#connection to the database
		engine = create_engine(db_uri)
		Session.configure(bind=engine)
		
		# get a handle on the metadata
		metadata = Base.metadata
		metadata.create_all(engine)     
					
	def get_user(self, login):
		try:
			login = unicode(login)		   
		except KeyError:
			return None

        # get a handle on the table object			
		users_table = User.__table__
		session = Session()
		search_path_query = "SET search_path TO %s" %(SCHEMA_SEARCH_PATH)
		set_search_path = session.execute(search_path_query)
		users = session.query(User).filter(User.username==login)
		results = users.all()
		session.close()
		
		if len(results) !=1:
			return None
		return results[0]					 
			
	def authenticate(self, environ, identity):
		userid = identity.get('repoze.who.plugins.auth_tkt.userid')
		if userid is None:
			try:
				password = unicode(identity['password'])
			except KeyError:
				return None
			user = self.get_user(identity['login'])		
			if user is not None and user.validate_password(password):				
				return user.username
			else:
				return None 
		else:
			return userid

						
	def __repr__(self):
		return '<%s %s>' % (self.__class__.__name__, id(self))	
		
def make_plugin(db_uri=None):	
	if db_uri is None:  
		raise ValueError('database configuration string must be specified')    
	return SqlalchemyWhoPlugin(db_uri)

